BASHシェルスクリプトで「キー入力待ち」プロンプトを実装する
BASHシェルスクリプト実行中に、
例えば下記のように表示させたい場面はよくあります。
実行しますか? (y or N):
ここで人間が「y
(あるいはYes
)」と入力しないと先に進まない、問題があればN
と入力して終了したり、CTRL
+C
で強制終了させたり。
そんなプロンプト機能を実装してみます。
先にネタばらしをすると、全部read
コマンドがやってくれます。
例1 : 「Hit enter key!」
単に実行を一時停止して、問題がなければエンター(リターン)キーを押すことで先に進むようなシェルスクリプトは、このようになります。
#!/bin/bash : (前段階の処理) read -p "Hit enter: " (続きの処理) :
単に「Hit enter: 」と表示して処理が一時停止します。エンター(リターン)キーを押せば先に進みます。
もし前段階の処理で何かしら問題が見つかれば、CTRL
+C
で強制終了させても良いでしょう。
例2 : 「ok? (y/N):」
Y
と入力しないと実行しない、Y
あるいはy
以外では終了させるようなパターンだと、このように書けます。
#!/bin/bash : (前段階の処理) read -p "ok? (y/N): " yn case "$yn" in [yY]*) ;; *) echo "abort." ; exit ;; esac (続きの処理) :
read
コマンドの末尾に書いてあるyn
は変数です。
キー入力した結果はここに格納されるので、次の行のcase
〜in
〜esac
で評価し条件分岐させています。
case
文ではパターンで指定が可能なので、
ここでは「大文字あるいは小文字の Y で始まるものは許可、そうでないものは終了(abort)」としています。
例3 : 「ok? (y/N):」をループ中に
例2の場合、「Y」としないとスクリプトが終了してしまいます。
これが例えば何かのループ処理中で、問題があっても飛ばすだけ、次の処理に移りたい場合もあるかと思います。
そんな場合は、このようにすると良いでしょう
#!/bin/bash : for X in "Blaze" "Edge" "Chopper" "Archer" do (前段階の処理) read -p "${X} : ok? (y/N):" yn case "$yn" in [yY]*) ;; *) echo "skipped." ; continue ;; esac (続きの処理) done :
continue
はexit
と違って、スクリプトは終了させません。次のループに進むだけです。
for
文以外にもwhile
文などでも使えます。
余録 : readコマンドのマニュアルページについて
ちなみに、man read
としてもread
コマンドのマニュアルページは出てきません。
$ man read BUILTIN(1) BSD General Commands Manual BUILTIN(1) NAME builtin, !, %, ., :, @, {, }, alias, alloc, bg, bind, bindkey, break, breaksw, builtins, case, cd, chdir, command, complete, continue, default, dirs, do, done, echo, echotc, elif, else, end, endif, endsw, esac, eval, exec, exit, export, false, fc, fg, filetest, fi, for, foreach, getopts, glob, goto, hash, :
これはread
が、BASHの組み込みコマンドだからです。ちょっと分かりづらいですね。
man bash
としてBASHのマニュアルページを表示したあと、SHELL BUILTIN COMMANDS
の章まで進んで下さい。手元の環境だと、だいたい2,600行目あたりでした。
read
コマンドにはいろいろと有用なオプションがあって、例えばパスワードを入力させる際に入力した文字列を表示させないオプションとかもあります。ちょっと全文引用するには量が多いので、是非ご自分でご確認下さい。